package com.example.yuanboot.common.config.datasource;

import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.Map;

/**
 * 动态数据源配置
 *
 * @author csp 2021-08-22
 */
@Configuration
@AutoConfigureAfter(MybatisPlusProperties.class)
public class DynamicDataSourceConfig {
    /**
     * Mybatis配置根据实际实现来，Mybatis、MybatisPlus
     */
    private final MybatisPlusProperties mybatisPlusProperties;
    private final DataSource master;
    private final DataSource slaver;

    public DynamicDataSourceConfig(MybatisPlusProperties mybatisPlusProperties, @Lazy DataSourceHolder dataSourceHolder, DataSource master, DataSource slaver) {
        this.mybatisPlusProperties = mybatisPlusProperties;
        this.master = master;
        this.slaver = slaver;
    }

    /**
     * 上下文中注册了多个数据源，通过primary指定主数据源
     * 否则MybatisAutoConfiguration或者MybatisPlusAutoConfiguration无法获取到数据源
     * (不太好使，虽然切换数据库了，但是主从挂掉一个，会一直刷拒绝连接的错误)
     */
    @Bean
    @Primary
    public DynamicDataSource dataSource() {
        // 通过AbstractRoutingDataSource去动态获取数据源
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setDefaultTargetDataSource(master);
        Map<Object, Object> build = MapUtil.builder().put("master", master).put("slaver", slaver).build();
        dynamicDataSource.setTargetDataSources(build);
        dynamicDataSource.afterPropertiesSet();
        dynamicDataSource.putAll(build);
        return dynamicDataSource;
    }



    /**
     * 因为已经移除了SpringBoot数据源自动配置
     * 需要手动创建sqlSessionFactory、sqlSessionTemplate及事务管理
     */
    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
//        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource());
        sqlSessionFactoryBean.setMapperLocations(mybatisPlusProperties.resolveMapperLocations());
        sqlSessionFactoryBean.setConfiguration(mybatisPlusProperties.getConfiguration());
        return sqlSessionFactoryBean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory());
    }

    @Bean
    public PlatformTransactionManager platformTransactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

}

